package motodev.app;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.microedition.rms.RecordStore;

public class RMS {
	

	private static final int BUFFER_SIZE=124;
	private static final String phone_2_linux_ResourceName="mmphone";
	private static final String linux_2_phone_ResourceName="mmlinux";
	private static final String linux_2_phone_ControlName="mmcontrol";
		
	private static final String cmd_prefix="sg";
	private static final byte cmd_null='*';
		
	static byte record_buffer[] = new byte[BUFFER_SIZE];	
	
	static byte last_seen_alternate_char=cmd_null;
	
	static final int alternate_char_offset=50; 
	static long send_message_count=0;
	static byte snd_msg_alternate_char=(byte)(send_message_count+alternate_char_offset);
	/*message format: prefix+alternat_char+length+msg*/
	
	static boolean read_control_successful=false;
	
	public static void reset_record()
	{
		byte control_buffer[]=new byte[1024];
		
		byte cmd_prefix_bytes[]=cmd_prefix.getBytes();
		//initial set of the record
		for(int i=0;i<BUFFER_SIZE;i++)			
			record_buffer[i]=cmd_null;
		
		for(int i=0;i<1024;i++)
			control_buffer[i]=cmd_null;
				
		for(int i=0;i<cmd_prefix.length();i++)
		{				
			record_buffer[i]=cmd_prefix_bytes[i];
			control_buffer[i]=cmd_prefix_bytes[i];
		}
		
		rms_save_bytes(record_buffer,phone_2_linux_ResourceName);
		rms_save_bytes(record_buffer,linux_2_phone_ResourceName);
		
		if(!read_control_successful && rms_load_string(linux_2_phone_ControlName)==null) //control file does not exist
			rms_save_bytes(control_buffer, linux_2_phone_ControlName); //initialize
	}
	
	public static void set_app_channel(byte ch) {
		/* ch:
		0 -> do not forward any message to me
		1 -> forward message with header (e.g. chat) only
		2 -> forward message without header (e.g. elevator) only
		255 -> forward all message */
		
		byte control_msg[] = new byte[3];
		control_msg[0] = (byte) 0xff; // phone_id: for control msg, it does not matter
		control_msg[1] = 0 ; //indicate it's a control message
		control_msg[2] = ch;
		send_cmd(control_msg);
	}
	
	public static void send_cmd(byte cmd[])
	{
	
		//send a command
		int start_pos=cmd_prefix.length();
		int msg_size=cmd.length;
		
		//add alternate char
		record_buffer[start_pos]=snd_msg_alternate_char;
		start_pos++;
		
		if(msg_size>BUFFER_SIZE-start_pos-1)
			msg_size=BUFFER_SIZE-start_pos-1;
		
		record_buffer[start_pos]=(byte)msg_size;
		
		for(int i=0;i<msg_size;i++)			
			record_buffer[start_pos+i+1]=cmd[i];
						
		int r=rms_save_bytes(record_buffer,phone_2_linux_ResourceName);
				
		int tries=2;
		
		while(r<0 && tries-- >0)
		{
			try
			{
				Thread.sleep(10);
				//r=rms_save_string(t, phone_2_linux_ResourceName);
				r=rms_save_bytes(record_buffer,phone_2_linux_ResourceName);
			}
			catch(Exception e)
			{				
			}
		}
		
		if(r>0)
		{
			send_message_count++;
			snd_msg_alternate_char=(byte)(send_message_count%2+alternate_char_offset);
		}
	}	
	
	public static final byte[] get_cmd()
	{
		
		//get a linux command
		
		byte[] rs=rms_load_bytes(linux_2_phone_ResourceName);
		int tries=2;
		while(rs==null && tries-- >0)
		{
			try
			{
				Thread.sleep(10);
				rs=rms_load_bytes(linux_2_phone_ResourceName);
			}
			catch(Exception e)
			{				
			}			
		}		
		
		if(rs==null) return null;
		
		int pre_len=cmd_prefix.length();
		
		if(rs[pre_len]==last_seen_alternate_char)
			return null;
		
		//check message
		int msg_len=rs[pre_len+1];
		if(msg_len<1 || msg_len>rs.length-pre_len-2) //too small or too big
			return null;
					
		last_seen_alternate_char=rs[pre_len];
		
		byte ret[]=new byte[msg_len];
		
		for(int i=0;i<msg_len;i++)
			ret[i]=rs[pre_len+2+i];
		
		return ret;
	}
	
	public static final String get_control_info()
	{
		//get a linux command
		byte rs[]=rms_load_bytes(linux_2_phone_ControlName);
		int tries=2;
		while(rs==null && tries-- >0)
		{
			try
			{
				Thread.sleep(10);
				rs=rms_load_bytes(linux_2_phone_ControlName);
			}
			catch(Exception e)
			{				
			}
		}
		
		if(rs==null) return null;
		
		int pre_len=cmd_prefix.length();
		
		if(rs[pre_len]==cmd_null)
			return null;
		
		//check message
		int msg_len=rs[pre_len+1];
		if(msg_len<1 || msg_len>rs.length-pre_len-2) //too small or too big
			return null;
		
		byte[] r=new byte[msg_len];
		for(int i=0;i<msg_len;i++)
			r[i]=rs[pre_len+2+i];
		
		read_control_successful=true;
		
		return new String(r);		
	}
	
	public RMS()
	{	
		
	}
	
	public static final String rms_loadres(String filename) {
		//load a string from the jar file		
        try {
            InputStream is =Connect4.class.getResourceAsStream(filename);
            if(is==null)
            	return null;
            
            StringBuffer str = new StringBuffer();
            byte b[] = new byte[1];
            while ( is.read(b) != -1 ) {
                str.append(new String(b));
            }
            is.close();
            return str.toString();
        }
        catch (IOException e) {
            e.printStackTrace();
            return null;
        }     
    }
    
    public static final void rms_delete(String delete) {
    	//deletes rms file. input string is filename
        try {
        RecordStore.deleteRecordStore(delete);
        } 
        catch (Exception e) {
        // Do some exception handling here
        }
    } 
    
    public static final String[] rms_list() {
    	//returns a list of all rms files
        try {
        	String[] output = RecordStore.listRecordStores();
        	return output;
        } 
        catch (Exception e) {
            return null;
        }
    }
    
    public static final int rms_save_bytes(byte[] data, String filename) {
    	RecordStore SettingStore;

    	try {
    	SettingStore = RecordStore.openRecordStore(filename,true);
    	if(SettingStore==null) return -1;

    	if(SettingStore.getNumRecords()==0)
    		SettingStore.addRecord(data,0,data.length);
    	else
    		SettingStore.setRecord(1, data, 0, data.length);
    	
    	SettingStore.closeRecordStore();
    	}
    	catch (Exception e) {
    		return -1;
    	}
    	return 1;
    }
    
    
    public static byte[] rms_load_bytes(String filename) {

    	RecordStore SettingStore;
    	
    	try {
    	SettingStore = RecordStore.openRecordStore(filename,false);
    	if(SettingStore==null) return null;

    	byte[] data = SettingStore.getRecord(1);    	
    	SettingStore.closeRecordStore();    	
    	return data;
    	} 
    	catch (Exception e) {
    		return null;    		
    	}
   }
   
   public static final int rms_save_string(String input, String filename) {
    	RecordStore SettingStore;
    	ByteArrayOutputStream baos;
    	DataOutputStream dos;
    	byte[] data;

    	try {
    	SettingStore = RecordStore.openRecordStore(filename,true);
    	if(SettingStore==null) return -1;

    	baos = new ByteArrayOutputStream();
    	dos = new DataOutputStream(baos);

    	dos.writeUTF(input);

    	data = baos.toByteArray();
    	if(SettingStore.getNumRecords()==0)
    	SettingStore.addRecord(data,0,data.length);
    	else
    	SettingStore.setRecord(1, data, 0, data.length);
    	SettingStore.closeRecordStore();

    	dos.close();
    	baos.close();
    	}
    	catch (Exception e) {
    		return -1;
    	}
    	return 1;
    } 
    public static final String rms_load_string(String filename) {

    	RecordStore SettingStore;
    	ByteArrayInputStream bais;
    	DataInputStream dis;
    	byte[] data;
    	String output;

    	try {
    	SettingStore = RecordStore.openRecordStore(filename,false);
    	if(SettingStore==null) return null;

    	data = SettingStore.getRecord(1);    	
    	bais = new ByteArrayInputStream(data);
    	dis = new DataInputStream(bais);

    	output=dis.readUTF();
    	dis.close();
    	bais.close();
    	SettingStore.closeRecordStore();    	
    	return output;
    	} 
    	catch (Exception e) {
    		return null;    		
    	}
   } 
}
